#ifndef GAMEMAP_H
#define GAMEMAP_H

#include "map.h"
#include <qpoint.h>
#include <qlist.h>

bool operator<(const QPoint& p1, const QPoint& p2);

struct AStarNode
{
    qint8 g_cost, h_cost, f_cost;
    QPoint parent;
    AStarNode() : g_cost(0), h_cost(0), f_cost(0) {}
    AStarNode(int n) : g_cost(n), h_cost(n), f_cost(n) {}
};

struct GameMapSquare
{
    Unit* unit;
    //Event* event;
};

class GameMap
{
public:

    GameMap(const QString& filePath, Tileset& tileset, const Team& team,const QString& filePathReal, bool b_special_fabinouz);

    virtual ~GameMap();

    bool gameIsOver() const;

    Map* getMap();
    Unit* getUnit(quint8 x, quint8 y) const;
    const QList<Unit*>& getUnits() const;
    Unit* getNextUnit();

    void setUnit(quint8 x, quint8 y, Unit* unit);
    bool containsUnit(quint8 x, quint8 y) const;

    //A* path finding
    QList<QPoint> findPath(const QPoint& start, const QPoint& target, UnitType unitType, quint8 remainingMoves, bool forceFreeDestination = false);
    //static quint32 abs(qint32 x);
    //static qint32 max(qint32 x, qint32 y);
    static quint8 taxicabDistance(quint8 x1, quint8 y1, quint8 x2, quint8 y2);
    static quint8 taxicabDistance(QPoint p1, QPoint p2);
    static CharDirection direction(quint8 x1, quint8 y1, quint8 x2, quint8 y2);

    void save();
    void read();

    void DestroyUnit(Unit* u);
    quint8 getTeamPerdante() { return equipePerdante; }

private:
    Map m_map;
    bool m_started;   //true if the game has started (playable characters have been placed) ; false otherwise
    bool m_gameOver;    //true if the game is over (one team won)
    QString m_name;
    quint8 m_width;
    quint8 m_height;
    GameMapSquare** m_matrix;
    QList<Unit*> m_units;   //contains the units in the order of their priority
    Team m_playerTeam;
    Team m_computerTeam;

    QFile m_file;

    //private A* methods
    void addAdjacentSquares(QPoint n);
    QPoint bestOpenedListNode();
    void addClosedList(QPoint p);
    QList<QPoint> retrievePath();

    //A* attributes
    UnitType m_unitType;
    AStarNode m_start;
    QPoint m_target;
    quint8 m_allowedMoves;
    bool m_forceFreeDestination;
    QMap<QPoint, AStarNode> m_closedList;
    QMap<QPoint, AStarNode> m_openedList;

    quint8 equipePerdante;
};

#endif // GAMEMAP_H
